using Microsoft.CSharp;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Specialized;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using System.Xml;
using System.Xml.Schema;
using Xml.Schema.Linq;
using Xml.Schema.Linq.CodeGen;
using Genuilder.Extensibility;
namespace Genuilder.Extensions.LinqToXsd
{
	public class XObjectsGenerator
	{
		ExtensionContext _Extension;
		public XObjectsGenerator(ExtensionContext extension)
		{
			_Extension = extension;
		}
		public void GenerateXObjects(string[] xsds, string csFileName, string configFile, bool xmlSerializable)
		{
			XmlSchemaSet set = new XmlSchemaSet();
			ValidationEventHandler veh = new ValidationEventHandler(ValidationCallback);
			set.ValidationEventHandler += veh;
			foreach(var xsd in xsds)
			{
				set.Add(null, XObjectsGenerator.CreateReader(xsd));
			}
			set.Compile();
			set.ValidationEventHandler -= veh;
			if(set.Count > 0 && set.IsCompiled)
			{
				GenerateXObjects(set, csFileName, configFile, null, xmlSerializable, false);
			}
		}
		private  void GenerateXObjects(XmlSchemaSet set, string csFileName, string configFileName, string assemblyName, bool xmlSerializable, bool nameMangler2)
		{
			LinqToXsdSettings configSettings = new LinqToXsdSettings(nameMangler2);
			if (configFileName != null)
			{
				configSettings.Load(configFileName);
			}
			configSettings.EnableServiceReference = xmlSerializable;
			XsdToTypesConverter xsdConverter = new XsdToTypesConverter(configSettings);
			ClrMappingInfo mapping = xsdConverter.GenerateMapping(set);
			CodeDomTypesGenerator codeGenerator = new CodeDomTypesGenerator(configSettings);
			CodeCompileUnit ccu = new CodeCompileUnit();
			foreach (CodeNamespace codeNs in codeGenerator.GenerateTypes(mapping))
			{
				ccu.Namespaces.Add(codeNs);
			}
			CSharpCodeProvider provider = new CSharpCodeProvider();
			if (csFileName != string.Empty && csFileName != null)
			{
				using (Update update = new Update(csFileName, Encoding.UTF8))
				{
					provider.GenerateCodeFromCompileUnit(ccu, update.Writer, new CodeGeneratorOptions());
				}
				PrintMessage(csFileName);
			}
		}
		private static XmlReader CreateReader(string xsdFile)
		{
			return XmlReader.Create(xsdFile, new XmlReaderSettings
			{
				DtdProcessing = DtdProcessing.Parse
			});
		}
		private  void PrintMessage(string csFileName)
		{
			_Extension.Logger.Info("Generated " + csFileName + "...");
		}
		private void PrintErrorMessage(string e)
		{
			_Extension.Logger.Error(String.Format("LinqToXsd: error TX0001: {0}", e));
		}
		private void PrintErrorMessage(ValidationEventArgs args)
		{
			_Extension.Logger.Error(String.Format("{0}({1},{2}): {3} TX0001: {4}", new object[]
			{
				args.Exception.SourceUri.Replace("file:///", "").Replace('/', '\\'),
				args.Exception.LineNumber,
				args.Exception.LinePosition,
				(args.Severity == XmlSeverityType.Warning) ? "warning" : "error",
				args.Message
			}));
		}
		
		private void ValidationCallback(object sender, ValidationEventArgs args)
		{
			PrintErrorMessage(args);
		}
	}
}
